---
title: providers의 빠른 초기화(Eager initialization)
version: 2
---

import { Link } from "/src/components/Link";
import { AutoSnippet } from "/src/components/CodeSnippet";
import consumerExample from "!!raw-loader!/docs/essentials/eager_initialization/consumer_example.dart";
import asyncConsumerExample from "!!raw-loader!/docs/essentials/eager_initialization/async_consumer_example.dart";
import requireValue from "/docs/essentials/eager_initialization/require_value";

모든 providers는 기본적으로 느리게(Lazy) 초기화됩니다. 
즉, provider는 처음 사용될 때만 초기화됩니다. 
이는 애플리케이션의 특정 부분에서만 사용되는 provider에 유용합니다.

안타깝게도 Dart의 작동 방식(tree shaking 목적)으로 인해 provider를 이른 초기화(eagerly initialized)해야 하는 것으로 플래그를 지정할 수 있는 방법은 없습니다. 
그러나 한 가지 해결책은 애플리케이션의 루트에서 초기화하려는 providers를 강제로 읽는(read) 것입니다.

권장되는 접근 방식은 `ProviderScope` 바로 아래에 배치된 소비자(Consumer)에서 provider를 단순히 "watch"하는 것입니다:

<AutoSnippet 
    raw={consumerExample} 
    translations={{
        render: "      // TODO: 여기에서 앱 렌더링",
        watch: "    // providers를 감시(watch)하여 providers를 빠른 초기화합니다.\n    // \"watch\"를 사용하면 provider가 폐기(disposed)되지 않고 계속 살아(alive) 있습니다.",
    }}
/>

:::note
초기화 소비자(initialization consumer)를 "MyApp" 또는 공개 위젯에 넣는 것을 고려해 보세요.
이렇게 하면 메인(main)에서 로직을 제거하여 테스트에서 동일한 동작을 사용할 수 있습니다.
:::

### FAQ

#### provider가 변경되면 전체 애플리케이션이 다시 빌드되지 않나요?

아니요, 그렇지 않습니다.
위의 샘플에서 열심히 초기화를 담당하는 Consumer는 별도의 위젯으로, `child`을 반환하는 것 외에는 아무것도 하지 않습니다.

핵심은 `MaterialApp` 자체를 인스턴스화하는 것이 아니라 `child`을 반환한다는 것입니다.
즉, `_EagerInitialization`이 리빌드되더라도 `child` 변수는 변경되지 않습니다. 
그리고 위젯이 변경되지 않으면 Flutter는 위젯을 다시 빌드하지 않습니다.

따라서 다른 위젯이 해당 provider를 수신하고 있지 않는 한 `_EagerInitialization`만 리빌드됩니다.

#### 이 접근 방식을 사용하면 로딩 및 오류 상태를 어떻게 처리할 수 있나요?

`Consumer`에서 일반적으로 처리하는 것처럼 로딩/오류 상태를 처리할 수 있습니다.
`_EagerInitialization`은 provider가 "loading" 상태인지 확인하고, 만약 그렇다면 `child` 대신 `CircularProgressIndicator`를 반환할 수 있습니다:

<AutoSnippet 
    raw={asyncConsumerExample} 
    translations={{
        states: "    // 오류 상태 및 로딩 상태 처리"
    }}
/>

#### 로딩/오류 상태를 처리했지만 다른 Consumer는 여전히 AsyncValue를 받습니다! 모든 위젯에서 로딩/에러 상태를 처리하지 않아도 되는 방법이 있나요?

provider가 `AsyncValue`를 노출하지 않도록 하는 대신 위젯이 `AsyncValue.requireValue`를 사용하도록 할 수 있습니다.  
이렇게 하면 패턴 매칭을 수행하지 않고도 데이터를 읽을 수 있습니다. 그리고 버그가 발생하면 명확한 메시지와 함께 예외를 던집니다.

<AutoSnippet 
    {...requireValue} 
    translations={{
        provider: "// 이른 초기화된 provider.",
        note: "    /// provider가 올바르게 초기화되었다면, \"requireValue\"로 데이터를 직접 읽을 수 있습니다.",
    }}
/>

:::note
이러한 경우 로딩/오류 상태를 노출하지 않는 방법(스코핑(scoping)에 의존)이 있지만 일반적으로 그렇게 하지 않는 것이 좋습니다.  
두 개의 providers를 만들고 오버라이드를 사용하는 복잡성을 감수할 가치가 없습니다.
:::
